/**
 * 
 */
package net.jbaez.code;

import java.lang.annotation.Annotation;
import java.util.Iterator;
import java.util.List;

/*
 * Copyright 2008 DynamiCode 
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *
 * http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an 
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 * either express or implied. See the License for the specific 
 * language governing permissions and limitations under the License. 
 */
//TODO Implementar los mensajes de error internacionalizados
/**
 * Clase comun de todos los elementos que 
 * pueden tener anotaciones
 */
public abstract class JAnnotatedElement {
	
	/*
	 * Arreglo con las anotaciones del
	 * elemento
	 */
	private List<JAnnotation> annotations;
	/*
	 * Nombre del elemento 
	 */
	private String name;
	
	/**
	 * Retorna el nombre del elemento
	 * @return El nombre del elemento
	 */
	public String getName(){
	    return name;
	}
	
	/**
	 * Asigna el nombre del elemento
	 * @param name Nombre a asignar
	 * @throws IllegalArgumentException Si el nombre no es un nombre valido
	 */
	protected final void setName(String name) throws IllegalArgumentException{
	    if(!CodeUtility.isValidName(name)) throw new IllegalArgumentException();
	    this.name = name;
	}
	
	/**
	 * Retorna las anotaciones presentes
	 * en el elemento
	 * @return Un arreglo con las anotaciones
	 * que posee el elemento o <code>null</code>
	 * si no existen anotaciones
	 */
	public JAnnotation[] getAnnotations(){
		if(annotations == null || annotations.isEmpty())
			return null;
		return (JAnnotation[]) annotations.toArray(new JAnnotation[]{});
	}
	/**
	 * Retorna la declaracion del tipo de anotacion
	 * solicitada
	 * @param clazz La clase de la anotacion
	 * @return La anotacion si esta presente o <code>null</code>
	 * si no existe la anotacion
	 */
	public JAnnotation getAnnotation(Class<? extends Annotation> clazz){
		if(annotations == null || annotations.isEmpty()) return null;
		//Creamos una anotacion a raiz de la clase
		//que nos han pasado
		JAnnotation annot = CodeUtility.createAnnotation(clazz);
		//Realizamos la busqueda por tipo
		return getAnnotation(annot.getType());
	}
	/**
	 * Retorna una annotation si esta presente 
	 * en el elemento anotado
	 * @param type Tipo de de anotacion
	 * @return Retorna la anotacion si esta presente
	 * o <code>null</code> si no esta presente
	 */
	public JAnnotation getAnnotation(IType<? extends JAnnotation> type){
		if(annotations == null || annotations.isEmpty()) return null;
		//Comparamos el tipo de cada anotacion para ver
		//si corresponde con alguna de los que esta en
		//la lista
		Iterator<JAnnotation> iter = annotations.iterator();
		while(iter.hasNext()){
		    JAnnotation annot = iter.next();
		    if(annot.getType().equals(type)) return annot;
		}
		//Si llegamos aca es por que no existe una annotacion
		//con es e tipo
		return null;
	}
	/**
	 * Retorna un valor que indica si la anotacion
	 * esta presente
	 * @param clazz Tipo de la anotacion
	 * @return <code>true</code> si existe o <code>false</code>
	 * si no 
	 */
	public boolean isAnnotationPresent(Class<? extends Annotation> clazz){
		return (getAnnotation(clazz) != null);
	}
	/**
	 * Verifica si existen una anotacion presente
	 * @param type El tipo a buscar
	 * @return <code>true</code> si existe la anotacion
	 * o <code>false</code> si no
	 */
	public boolean isAnnotationPresent(IType<? extends JAnnotation> type){
		//Obtenemos la anotacion
	    	return (getAnnotation(type) != null);
	}
	
}
